package elitequant.position;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import elitequant.order.FillEvent;

/**
 * PortfolioManager is one component of PortfolioManager
 *
 */
public class PortfolioManager {
    
    private BigDecimal cash;
    
    private Map<String, Position> positions;
    
    public PortfolioManager(BigDecimal initialCash) {
        cash = initialCash;
        positions = new HashMap<String, Position>();
    }
    
    /**
     * get initial position(commission=0.0)
     * @param symbol
     * @param price
     * @param quantity
     */
    public void onPosition(String symbol, double price, int quantity) {
        onPosition(symbol, price, quantity, 0.0);
    }
    
    /**
     * get initial position
     * @param symbol
     * @param price
     * @param quantity
     * @param commission
     */
    public void onPosition(String symbol, double price, int quantity, double commission) {
        synchronized (positions) {// for thread safe
            Position position = positions.get(symbol);
            if(position == null) {
                positions.put(symbol, position);
            }
            else {
                System.out.println(String.format("Symbol %s already exists in the portfolio ", position.getFullSymbol()));
            }
        }
    }
    
    /**
     * This works only on stocks.
     * TODO: consider margin
     * 
     * @param fillEvent
     */
    public void onFill(FillEvent fillEvent) {
        // sell will get cash back
        cash = cash.subtract(
                BigDecimal.valueOf(fillEvent.fillSize)
                .multiply(fillEvent.fillPrice)
                .add(fillEvent.commission)
                );

        synchronized (positions) {// for thread safe
            Position position = positions.get(fillEvent.fullSymbol);
            if(position != null){     // adjust existing position
                position.onFill(fillEvent);
            }
            else{
                positions.put(fillEvent.fullSymbol, fillEvent.toPosition());
            }
        }
    }
    
    public void markToMarket(Date currentTime, String symbol, BigDecimal lastPrice) {
        Position position = positions.get(symbol);
        if(position != null) {
            position.markToMarket(lastPrice);
        }
    }

    public Map<String, Position> getPositions() {
        return positions;
    }

    public BigDecimal getCash() {
        return cash;
    }

}
